# -*- coding: utf-8 -*-
# Clase principal de la aplicación que genera el widget contenedor principal.
# Contiene barra de herramientas superior (impresión, accesos directos, 
# consultas web).				

## vipera, un diseñador de aplicaciones para Python
##     Copyright (C) 2011 Ángel Luis García García
##
##    This program is free software: you can redistribute it and/or modify
##    it under the terms of the GNU General Public License as published by
##    the Free Software Foundation, either version 3 of the License, or
##    (at your option) any later version.
##
##    This program is distributed in the hope that it will be useful,
##    but WITHOUT ANY WARRANTY; without even the implied warranty of
##    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##    GNU General Public License for more details.
##
##    You should have received a copy of the GNU General Public License
##    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import wx
import wx.lib.agw.hyperlink as enlace_web
import wx.lib.agw.pybusyinfo as PBI

import os
import time
 
from frontend_base import frame_principal, dialogo_salir_p
from impresion_vipera import dialogo_impresion_p
from impresion_vipera import f_configurar_impresion
from rss_vipera import Dialogo_rss
from configuracion_vipera import proy_por_defecto
from configuracion_vipera import conf_vipera
from i18n_vipera import t
from acerca_de_vipera import f_acercade_vipera

def f_guardar_conf_vipera(panel_conf_vipera):
    '''Función para guardar datos de configuración de la aplicación'''       
    # Datos generales.
    # titulo_aplic = panel_conf_vipera.m_textCtrl_titulo.GetValue()
    activar_tips = panel_conf_vipera.m_checkBox_tips.Get3StateValue()
    color_back = panel_conf_vipera.m_colourPicker_back.GetColour()
    idioma = panel_conf_vipera.m_choice_idioma.GetStringSelection()
    alto_ogl = panel_conf_vipera.m_spinCtrl_alto_ogl.GetValue()
    ancho_ogl = panel_conf_vipera.m_spinCtrl_ancho_ogl.GetValue()
    tope_hor_ogl = panel_conf_vipera.m_spinCtrl_tope_hor_ogl.GetValue()
    color_back_ogl = panel_conf_vipera.m_colourPicker_back_ogl.GetColour()
    # Creamos diccionario.
    datos = {'color_back' : color_back,
             'activar_tips' : activar_tips,
             'idioma' : idioma,
             'alto_ogl' : alto_ogl,
             'ancho_ogl' : ancho_ogl,
             'tope_hor_ogl' : tope_hor_ogl,
             'color_back_ogl' : color_back_ogl}
    
    # Guardamos configuración de la aplicación en disco.
    conf_vipera_p = conf_vipera()
    # conf_vipera_p.abrir_fichero()
    conf_vipera_p.guardar_fichero(datos)

class fp(frame_principal):
    '''Frame principal de la aplicación'''
    def __init__(self, datos_conf, idioma):
        '''Constructor de clase'''
        frame_principal.__init__(self, datos_conf, idioma)
        # Icono de la aplicación.
        icono = wx.EmptyIcon()
        icono.CopyFromBitmap(wx.Bitmap(proy_por_defecto['icon_aplic'], wx.BITMAP_TYPE_ANY))
        self.SetIcon(icono)
        # Centramos el frame.
        self.Centre()
        # [22-09-2011] Incluimos componente de impresión.
        self.PrintData = wx.PrintData()
        self.PrintData.SetPaperId(wx.PAPER_A4)
        self.PrintData.SetPrintMode(wx.PRINT_MODE_PRINTER)
        # [19-09-2011] Colores del frame de la aplicación.
        self.SetBackgroundColour(datos_conf['color_back'])
        # Enlaces directos de operaciones de proyecto.
        self.nuevo_proyecto = wx.BitmapButton(self, -1, 
                                              wx.Bitmap(u"recursos/images/nuevo_proyecto_vipera.png", wx.BITMAP_TYPE_ANY), 
                                              wx.DefaultPosition, wx.DefaultSize, wx.BU_AUTODRAW)
        self.nuevo_proyecto.SetToolTipString( t(u"Nuevo proyecto", self.l))
        self.abrir_proyecto = wx.BitmapButton(self, -1, 
                                              wx.Bitmap(u"recursos/images/abrir_proyecto_vipera.png", wx.BITMAP_TYPE_ANY), 
                                              wx.DefaultPosition, wx.DefaultSize, wx.BU_AUTODRAW)
        self.abrir_proyecto.SetToolTipString(t(u"Abrir proyecto", self.l))
        self.salvar_proyecto = wx.BitmapButton(self, -1, 
                                               wx.Bitmap(u"recursos/images/salvar_proyecto_vipera.png", wx.BITMAP_TYPE_ANY), 
                                               wx.DefaultPosition, wx.DefaultSize, wx.BU_AUTODRAW)
        self.salvar_proyecto.SetToolTipString(t(u"Salvar proyecto",self.l))
        self.designer_icono = wx.BitmapButton(self, -1, 
                                              wx.Bitmap(u"recursos/images/design_vipera.png", wx.BITMAP_TYPE_ANY), 
                                              wx.DefaultPosition, wx.DefaultSize, wx.BU_AUTODRAW)
        self.designer_icono.SetToolTipString(t(u"Diseñador", self.l))
        self.ing_inversa_icono = wx.BitmapButton(self, -1, 
                                                 wx.Bitmap(u"recursos/images/ing_inversa_vipera.png", wx.BITMAP_TYPE_ANY), 
                                                 wx.DefaultPosition, wx.DefaultSize, wx.BU_AUTODRAW)
        self.ing_inversa_icono.SetToolTipString(t(u"Ingeniería inversa", self.l))
        self.pyshell_icono = wx.BitmapButton(self, -1, 
                                             wx.Bitmap(u"recursos/images/pyshell_vipera.png", wx.BITMAP_TYPE_ANY), 
                                             wx.DefaultPosition, wx.DefaultSize, wx.BU_AUTODRAW)
        self.pyshell_icono.SetToolTipString( u"Pyshell")
        self.imprimir = wx.BitmapButton(self, -1, 
                                        wx.Bitmap(u"recursos/images/impresora_vipera.png", wx.BITMAP_TYPE_ANY), 
                                        wx.DefaultPosition, wx.DefaultSize, wx.BU_AUTODRAW)
        self.imprimir.SetToolTipString(t(u"Area de impresión", self.l))
        self.search = wx.SearchCtrl(self, -1, style = wx.TE_PROCESS_ENTER)
        self.search.SetToolTipString(t(u"Búsqueda en el nido de Python", self.l))
        self.noticias = wx.BitmapButton(self, -1, 
                                        wx.Bitmap(u"recursos/images/noticias_vipera.png", wx.BITMAP_TYPE_ANY), 
                                        wx.DefaultPosition, wx.DefaultSize, wx.BU_AUTODRAW)
        self.noticias.SetToolTipString(u"RSS www.python.org")
        self.link_python = wx.BitmapButton(self, -1, 
                                           wx.Bitmap(u"recursos/images/logo_python_vipera.png", wx.BITMAP_TYPE_ANY), 
                                           wx.DefaultPosition, wx.DefaultSize, wx.BU_AUTODRAW)
        self.link_python.SetToolTipString(u"www.python.org")
        self.config_aplic_icono = wx.BitmapButton(self, -1, 
                                                  wx.Bitmap(u"recursos/images/conf_aplic_vipera.png", wx.BITMAP_TYPE_ANY), 
                                                  wx.DefaultPosition, wx.DefaultSize, wx.BU_AUTODRAW)
        self.config_aplic_icono.SetToolTipString(t(u"Configuración de la aplicación", self.l))
        self.tutorial_icono = wx.BitmapButton(self, -1, 
                                              wx.Bitmap(u"recursos/images/tutorial_vipera.png", wx.BITMAP_TYPE_ANY), 
                                              wx.DefaultPosition, wx.DefaultSize, wx.BU_AUTODRAW)
        self.tutorial_icono.SetToolTipString(t(u"Tutorial de la aplicación", self.l))
        self.acercade_icono = wx.BitmapButton(self, -1, 
                                              wx.Bitmap(u"recursos/images/acercade_vipera.png", wx.BITMAP_TYPE_ANY), 
                                              wx.DefaultPosition, wx.DefaultSize, wx.BU_AUTODRAW)
        self.acercade_icono.SetToolTipString(t(u"Acerca de...", self.l))
        self.salir = wx.BitmapButton(self, -1, 
                                     wx.Bitmap(u"recursos/images/salir_vipera.png", wx.BITMAP_TYPE_ANY), 
                                     wx.DefaultPosition, wx.DefaultSize, wx.BU_AUTODRAW)
        self.salir.SetToolTipString(t(u"Salir", self.l))
        # Añadimos a la barra1.
        self.barra1.Add(self.nuevo_proyecto, 0, wx.ALL|wx.EXPAND, 2)
        self.nuevo_proyecto.Bind(wx.EVT_BUTTON, self.OnNuevo)
        self.barra1.Add(self.abrir_proyecto, 0, wx.ALL|wx.EXPAND, 2)
        self.abrir_proyecto.Bind(wx.EVT_BUTTON, self.OnAbrir)                
        self.barra1.Add(self.salvar_proyecto, 0, wx.ALL|wx.EXPAND, 2)
        self.salvar_proyecto.Bind(wx.EVT_BUTTON, self.OnSalvar)
        self.barra1.AddSpacer((0, 0), 0, wx.EXPAND, 5)        
        self.barra1.Add(self.designer_icono, 0, wx.ALL|wx.EXPAND, 2)
        self.designer_icono.Bind(wx.EVT_BUTTON, self.OnDesigner)
        self.barra1.Add(self.ing_inversa_icono, 0, wx.ALL|wx.EXPAND, 2)
        self.ing_inversa_icono.Bind(wx.EVT_BUTTON, self.OnIngInv)
        self.barra1.Add(self.pyshell_icono, 0, wx.ALL|wx.EXPAND, 2)
        self.pyshell_icono.Bind(wx.EVT_BUTTON, self.OnPyshell)
        self.barra1.Add(self.imprimir, 0, wx.ALL|wx.EXPAND, 2)
        self.imprimir.Bind(wx.EVT_BUTTON, self.OnImprimir)
        self.barra1.AddSpacer((0, 0), 1, wx.EXPAND, 5)
        self.barra1.Add(self.search, 0, wx.ALL|wx.EXPAND, 2)
        self.search.Bind(wx.EVT_SEARCHCTRL_SEARCH_BTN, self.OnSearch)
        self.search.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
        self.barra1.Add(self.noticias, 0, wx.ALL|wx.EXPAND, 2)
        self.noticias.Bind(wx.EVT_BUTTON, self.OnNoticias)
        self.barra1.Add(self.link_python, 0, wx.ALL|wx.EXPAND, 2)
        self.link_python.Bind(wx.EVT_BUTTON, self.OnLink)                
        self.barra1.AddSpacer((0, 0), 1, wx.EXPAND, 5)
        self.barra1.Add(self.config_aplic_icono, 0, wx.ALL|wx.EXPAND, 2)
        self.config_aplic_icono.Bind(wx.EVT_BUTTON, self.OnConfAplic)
        self.barra1.Add(self.tutorial_icono, 0, wx.ALL|wx.EXPAND, 2)
        self.tutorial_icono.Bind(wx.EVT_BUTTON, self.OnTutorial)
        self.barra1.Add(self.acercade_icono, 0, wx.ALL|wx.EXPAND, 2)
        self.acercade_icono.Bind(wx.EVT_BUTTON, self.OnAcercaDe)
        self.barra1.Add(self.salir, 0, wx.ALL|wx.EXPAND, 2)
        self.salir.Bind(wx.EVT_BUTTON, self.OnSalirIcono)
        # Otros bindings...
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.gestion_proy.m_bpButton_nuevo.Bind(wx.EVT_BUTTON, self.OnNuevo)
        self.gestion_proy.m_bpButton_abrir.Bind(wx.EVT_BUTTON, self.OnAbrir)        
        self.gestion_proy.m_bpButton_salvar.Bind(wx.EVT_BUTTON, self.OnSalvar)        
        
    def OnSalirIcono(self, event):
        '''Click en icono de salida'''
        self.salida_aplicacion()

    def OnLink(self, event):
        '''Abrir navegador para www.python.org'''
        lanzadera_web = enlace_web.HyperLinkCtrl(self, -1)
        lanzadera_web.Show(False)
        lanzadera_web.GotoURL("http://www.python.org", True, False)    
        # Nos limpiamos el objeto lanzadera.
        lanzadera_web.Destroy()

    # ###################
    # Métodos de soporte.
    # ###################

    def __nuevo(self):
        '''Nuevo proyecto'''
        # Creamos nuevo proyecto.
        self.gestion_proy.nuevo_proyecto(self.panel, self.l)

    def __salvar(self):
        '''Salvar proyecto'''
        # Si existe el proyecto, hay que preguntar.
        nombre_proyecto = self.panel.panel_conf_vipera.m_textCtrl_nproy.GetValue()
        ruta = '%s%s%s.%s' % (proy_por_defecto['carpeta_proyecto'], 
                              proy_por_defecto['sep'],
                              nombre_proyecto,
                              proy_por_defecto['ext_proy'])
        seguir = True
        if os.path.exists(ruta):
            msj = t(u'El proyecto existe. ¿Sobreescribir?', self.l)
            i = wx.MessageBox(msj, t(u"Atención", self.l), wx.YES_NO)
            if i != wx.YES: seguir = False
        if seguir:
            # Salvamos proyecto.
            ret = self.gestion_proy.salvar_proyecto(self.panel, self.l)
            if ret != -1: 
                # Nombre del proyecto en barra de estado.
                nproy = u'Proyecto ' + self.panel.panel_conf_vipera.m_textCtrl_nproy.GetValue()
                nproy = t(nproy, self.l)
                self.barra_estado.set_texto_statusbar(nproy, 0)
                # Info...
                wx.MessageBox(t(u"Se salvó el proyecto", self.l), 
                                        t(u"Información", self.l),wx.OK)
        else: ret = -1
        return ret

    def __limpieza(self):
        '''Limpieza de memoria'''
        # Información de limpieza.
        mensaje = t(u"Limpiando memoria...", self.l)
        busy = PBI.PyBusyInfo(mensaje, parent=None, title=t("Un momento...", self.l))
        # Eliminamos relojes...
        self.barra_estado.timer.Stop()
        del self.barra_estado.timer
        # Además se destruyen todos los posibles procesos...
        self.panel.panel_editor.matar_proceso()
        # Plataforma Microsoft Windows.
        if os.name == 'nt':
            # Dejamos 2 segundos para que de tiempo al hilo...           
            time.sleep(2)
        if os.name == 'posix':
            # No hacemos nada
            time.sleep(2)
        # Limpiamos mensaje.
        del busy
            
    def salida_aplicacion(self, dialogo_salir = True):
        '''Salir de la aplicación'''
        if dialogo_salir:
            a = dialogo_salir_p(self, self.l)
            a.Show()
            if a.ShowModal() == wx.ID_OK:
                salir = True
                if a.m_checkBox_salvar.IsChecked():
                    if self.__salvar() == -1: salir = False
            else: salir = False
            # Limpiamos procesos de memoria.
            # self.__limpieza()
            # Limpiamos diálogo de salida.
            a.Destroy()
            if salir: 
                # Limpiamos procesos de memoria.
                self.__limpieza()
                # [19-09-2011] Guardamos datos de configuración de la aplicación.
                f_guardar_conf_vipera(self.conf_vipera)
                # Destruimos el frame principal.
                self.Destroy()
        else:
            # Limpiamos procesos de memoria.
            self.__limpieza()
            # Guardamos configuración y salimos.
            f_guardar_conf_vipera(self.conf_vipera)
            # Destruimos el frame principal.
            self.Destroy()
            
    # ##########################################
    # Manejadores de eventos de accesos directos
    # ##########################################

    def OnAcercaDe(self, event):
        '''Acerca de'''
        f_acercade_vipera(self, self.l)

    def OnConfAplic(self, event):
        '''Acceso directo a configuración de la aplicación'''
        self.choiceBook.SetSelection(4)
        
    def OnTutorial(self, event):
        '''Lanzamiento del tutorial de la aplicación'''
        # Lanzamos el tutorial en el navegador.
        lanzadera_web = enlace_web.HyperLinkCtrl(self, -1)
        lanzadera_web.Show(False)
        lanzadera_web.GotoURL(proy_por_defecto['tutorial_html'], True, False)    
        # Nos limpiamos el objeto lanzadera.
        lanzadera_web.Destroy()

    def OnDesigner(self, event):
        '''Acceso directo al Diseñador'''
        self.choiceBook.SetSelection(1)
        
    def OnIngInv(self, event):
        '''Acceso directo a Ingeniería Inversa y Editor'''
        self.choiceBook.SetSelection(2)

    def OnPyshell(self, event):
        '''Acceso directo a Pyshell'''
        self.choiceBook.SetSelection(3)
                
    def OnNuevo(self, event):
        '''Crear un proyecto nuevo'''
        i = wx.MessageBox(t(u"¿Crear nuevo proyecto?", self.l), t(u"Nuevo", self.l), wx.YES_NO)
        if i != wx.YES: return -1
        self.__nuevo()
        self.choiceBook.SetSelection(1)
        # Nombre del proyecto en barra de estado.
        nproy = t(u'Proyecto sin nombre...', self.l)
        self.barra_estado.set_texto_statusbar(nproy, 0)

    def OnSalvar(self, event):
        '''Salvar/guardar el proyecto actual a disco'''
        self.__salvar()

    def OnAbrir(self, event):
        '''Cargar un proyecto de disco'''
        # Obtenemos referencias de paneles.
        if self.gestion_proy.abrir_proyecto(self.panel, self.l):
            # Vamos al diseñador.
            self.choiceBook.SetSelection(1)
            # Cargamos lista de módulos en el área del 
            # configurador y documentación del proyecto.
            self.panel.panel_conf_vipera.cargar_nombres_modulos_en_doc()
            # Nombre del proyecto en barra de estado.
            nproy = t(u'Proyecto', self.l) + ' ' + unicode(self.panel.panel_conf_vipera.m_textCtrl_nproy.GetValue())
            # nproy = t(nproy, self.l)
            self.barra_estado.set_texto_statusbar(nproy, 0)
        
    def OnClose(self, event):
        '''Event handler de salida de la aplicación'''
        self.salida_aplicacion()

    def OnSearch(self, event):
        '''Búsqueda de comandos en nido de Python'''
        lanzadera_web = enlace_web.HyperLinkCtrl(self, -1)
        lanzadera_web.Show(False)
        cadena = self.search.GetValue()
        cadena_web = proy_por_defecto['cadena_web'] % cadena
        lanzadera_web.GotoURL(cadena_web, True, False)
        # Nos limpiamos el objeto lanzadera.
        lanzadera_web.Destroy()

    def OnImprimir(self, event):
        '''Lanzar área de impresión'''
        dialogo = dialogo_impresion_p(self, 
                                      self, 
                                      self.PrintData, 
                                      proy_por_defecto['fich_imp'],
                                      proy_por_defecto['fich_html'], idioma = self.l)
        dialogo.Show()
        dialogo.ShowModal()
        # Pasamos el nuevo objeto de impresión para guardar los cambios.
        self.PrintData = dialogo.print_data
        # Limpiamos...
        dialogo.Destroy()

    def OnNoticias(self, event):
        '''Lanzamiento de noticias RSS'''
        a = Dialogo_rss(self, idioma = self.l)
        a.ShowModal()
        a.Destroy()
